/**
 * @ date 2020-02-27
 * @ description AjaxSelect 下拉框（初始化数据源下拉框；模糊查询异步搜索下拉框）
 */

import * as React from 'react';
import { Select, Spin } from 'antd';
import { useLocalStore, observer } from 'mobx-react-lite';
import { SelectProps } from 'antd/lib/select';
import { getConfig, ValidConfigKeys } from './config';

const Option = Select.Option;

const formatMapObject = (data: any) => Object.entries(data).map((item) => ({
  key: item[0],
  label: item[1],
}));

interface Props extends SelectProps<any> {
  type?: ValidConfigKeys
  params?: {}
  keyName?: string
  valueName?: string
  ajaxSearchKey?: string
  placeholder?: string
  ajaxSearch?: boolean
  children?: React.ReactNode
}

const AjaxSelect = observer((props: Props) => {
  const config = React.useMemo(() => getConfig(props.type), [props.type]);

  const state = useLocalStore(() => {
    const { children, ...rest } = props;

    return {
      ...config,
      ...rest,
      options: [],
      loading: false,
    };
  });

  const initData = async (params?: any) => {
    if (!config.api) {
      return;
    }

    state.loading = true;

    const res = await config.api({
      ...params,
    }).catch(() => {
      state.loading = false;
    });

    let ajaxOptions = [];

    if (res?.data) {
      if (Array.isArray(res.data)) {
        // array
        ajaxOptions = res.data.map((item: any) => (
          <Option
            key={item[state.keyName]}
            value={item[state.keyName].toString()}
          >
            {item[state.valueName]}
          </Option>
        ));
      } else {
        // object (map 格式)
        ajaxOptions = formatMapObject(res.data).map(
          (item: any) => (
            <Option key={item.key} value={item.key.toString()}>
              {item.label}
            </Option>
          ),
        );
      }
    }

    state.options = ajaxOptions;
    state.loading = false;
  };

  const ajaxFetch = (value: any) => {
    initData({
      [state.ajaxSearchKey]: value,
    });
  };

  const filterOptionFunction = (input: string, option: any) => {
    const children = option.children;

    if (children) {
      return children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
    }

    return false;
  };

  React.useEffect(() => {
    if (state.init) {
      initData(state.params);
    }
  }, []);

  return (
    <Select
      allowClear={true}
      showSearch={true}
      notFoundContent={
        state.loading
          ? <Spin size="small" />
          : <span className="text-gray-500">No Data</span>
      }
      filterOption={filterOptionFunction}
      onSearch={state.ajaxSearch ? ajaxFetch : undefined}
      placeholder={state.placeholder}
      {...props}
    >
      {props.children ? props.children : state.options}
    </Select>
  );
});

export default AjaxSelect;
